import numpy as np
import pandas as pd
from pandas import DataFrame
from sklearn.decomposition import PCA


class PCA_:

    def __init__(self, dataset, args):
        self.dataset = dataset
        self.input_dim = args.get('input_dim', 10)
        self.output_dim = args.get('output_dim', 1)
        self.n_components = args.get('n_components', 5)
        self.weights = args.get('weights', 'uniform')  # uniform, distance

        df = pd.read_csv(dataset, delimiter=',', header=None)
        self.X, self.y = df.values[:, :self.input_dim], df.values[:, -self.output_dim]

    def run(self):
        pca = PCA(n_components=self.n_components)
        X = pca.fit(self.X).transform(self.X)
        df = DataFrame(np.c_[X, self.y])
        res = [{k: round(v, 5) for k, v in zip(range(self.n_components), row)} for row in df.values.tolist()]
        return {
            'Result': res,
            'ExplainedVarianceRatio': round(float(sum(pca.explained_variance_ratio_)), 4),
            'Description': 'PCA（principal components analysis）即主成分分析技术，又称主分量分析。'
                           '主成分分析也称主分量分析，旨在利用降维的思想，把多指标转化为少数几个综合指标。'
                           '在统计学中，主成分分析PCA是一种简化数据集的技术。它是一个线性变换。'
                           '这个变换把数据变换到一个新的坐标系统中，使得任何数据投影的第一大方差在第一个坐标(称为第一主成分)上，第二大方差在第二个坐标(第二主成分)上，依次类推。'
                           '主成分分析经常用于减少数据集的维数，同时保持数据集的对方差贡献最大的特征。'
                           '这是通过保留低阶主成分，忽略高阶主成分做到的。这样低阶成分往往能够保留住数据的最重要方面。'
        }


if __name__ == '__main__':
    print(PCA_('../../data/sterilizedmilk_for_classfication.csv', {}).run())

# import numpy as np
# import json
# import matplotlib.pyplot as plt
# from sklearn.datasets.samples_generator import make_blobs
#
# class PCA:
#     def __init__(self, dataset, **kwargs):
#         self.dataset = dataset
#
#     def store(self):
#         data = {'data': ['pca_dataset1_1.png', 'pca_dataset1_2.png'], 'status': 1}
#         with open('../../result/pca_dataset1.json', 'w') as fw:
#             json.dump(data, fw)
#
#     def run(self):
#         X, y = make_blobs(n_samples=10000, n_features=3, centers=[[3, 3, 3], [0, 0, 0], [1, 1, 1], [2, 2, 2]],
#                           cluster_std=[0.2, 0.1, 0.2, 0.2], random_state=9)
#
#         eigvalue, eigvector = np.linalg.eig(np.cov(X.T))
#
#         a = np.hstack((eigvector[:, 0].reshape(3, -1), eigvector[:, -1].reshape(3, -1)))
#         X = X - X.mean(axis=0)
#         X_new1 = X.dot(a)
#
#         plt.scatter(X_new1[:, 0], X_new1[:, 1], marker='o')
#         plt.savefig('../../result/pca_dataset1_2.png')
#
#         self.store()
